<template>
  <div class="dialog-full">
    <el-dialog
      :title="$t('cms.customFieldDesign')"
      :model-value="modelValue"
      destroy-on-close
      fullscreen
      @update:model-value="(event) => $emit('update:modelValue', event)"
    >
      <el-container class="border-t" style="height: calc(100vh - 65px)">
        <el-aside width="300px">
          <el-scrollbar class="h-full">
            <el-card class="box-card">
              <draggable
                :list="components"
                :group="{ name: 'components', pull: 'clone', put: false }"
                :sort="false"
                :clone="clone"
                item-key="label"
                @end="onEnd"
              >
                <template #item="{ element }">
                  <div class="drag-component">{{ element.label }}</div>
                </template>
              </draggable>
            </el-card>
          </el-scrollbar>
        </el-aside>
        <el-container class="border-r border-l">
          <el-header height="auto" class="px-2 py-1">
            <el-button :loading="buttonLoading" type="primary" @click.prevent="handleSubmit">{{
              $t('common.save')
            }}</el-button>
          </el-header>
          <el-main class="border-t p-0">
            <el-scrollbar class="drawing-board h-full p-2">
              <el-form :model="drawingFormData" label-width="150px" class="h-full">
                <draggable
                  :list="customs"
                  class="min-h-full content-start mx-0"
                  tag="el-row"
                  :component-data="{ gutter: 8 }"
                  :animation="250"
                  group="components"
                  item-key="code"
                  @start="() => (drag = true)"
                  @end="() => (drag = false)"
                >
                  <template #item="{ element: field }">
                    <el-col :span="field.double ? 12 : 24" class="relative">
                      <el-form-item
                        :prop="field.code"
                        :required="field.required"
                        class="mb-0 py-3"
                      >
                        <template #label><label-tip :label="field.name" /></template>
                        <field-item
                          v-model="field.defaultValue"
                          v-model:model-key="field.defaultValueKey"
                          :field="field"
                        />
                      </el-form-item>
                      <div
                        :class="[
                          'drag-mask',
                          !drag && selected !== field ? 'hover:opacity-10' : null,
                          selected === field ? 'drag-mask-selected' : null
                        ]"
                        @click="() => changeSelected(field)"
                      ></div>
                      <div
                        v-if="!field.required"
                        :class="['drag-close', selected !== field ? 'hidden' : null]"
                        @click="() => deleteElement(field)"
                      >
                        <el-icon class="text-danger"><remove /></el-icon>
                      </div>
                    </el-col>
                  </template>
                </draggable>
              </el-form>
            </el-scrollbar>
          </el-main>
        </el-container>
        <el-aside class="right-panel w-64">
          <el-scrollbar class="h-full pt-0.5 pb-3">
            <el-tabs v-model="currentTab" stretch>
              <el-tab-pane :label="$t('cms.model.attribute')" name="attribute" class="px-2">
                <el-form ref="selectedForm" :model="selected">
                  <field-attribute v-if="selected" :selected="selected" />
                </el-form>
              </el-tab-pane>
            </el-tabs>
          </el-scrollbar>
        </el-aside>
      </el-container>
    </el-dialog>
  </div>
</template>
<script lang="ts">
export default { name: 'FormCustomField' }
</script>
<script setup lang="ts" name="FormCustomField">
import LabelTip from '@/components/cms/LabelTip.vue'
import * as ModelApi from '@/api/cms/model'
import { ref, toRefs, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { Remove } from '@element-plus/icons-vue'
import { useI18n } from 'vue-i18n'
import draggable from 'vuedraggable'
import FieldItem from './component/FieldItem.vue'
import FieldAttribute from './component/FieldAttribute.vue'
import { getRandomLower } from '@/utils/cmscommon'

const props = defineProps({
  modelValue: { type: Boolean, required: true },
  beanId: { type: Number, default: null }
})
const emit = defineEmits({ 'update:modelValue': null })

const { beanId, modelValue: visible } = toRefs(props)
const { t } = useI18n()
const bean = ref<any>({})
const drawingFormData = ref<any>({})
const selectedForm = ref<any>()
const drag = ref<boolean>(false)
const selected = ref<any>()
const cloned = ref<any>()
const currentTab = ref<string>('attribute')
const buttonLoading = ref<boolean>(false)
//自定义组件
//{ label: t('cms.model.fieldType.slider'), type: 'slider', custom: true },
//{ label: t('cms.model.fieldType.switch'), type: 'switch', custom: true },

const components = ref<any[]>([
  { label: t('cms.model.fieldType.text'), type: 'text', custom: true },
  { label: t('cms.model.fieldType.textarea'), type: 'textarea', custom: true },
  { label: t('cms.model.fieldType.number'), type: 'number', custom: true },
  { label: t('cms.model.fieldType.date'), type: 'date', custom: true },
  { label: t('cms.model.fieldType.color'), type: 'color', custom: true },
  { label: t('cms.model.fieldType.radio'), type: 'radio', custom: true },
  { label: t('cms.model.fieldType.checkbox'), type: 'checkbox', custom: true },
  { label: t('cms.model.fieldType.select'), type: 'select', custom: true },
  { label: t('cms.model.fieldType.multipleSelect'), type: 'multipleSelect', custom: true },
  { label: t('cms.model.fieldType.imageUpload'), type: 'imageUpload', custom: true },
  { label: t('cms.model.fieldType.videoUpload'), type: 'videoUpload', custom: true },
  { label: t('cms.model.fieldType.audioUpload'), type: 'audioUpload', custom: true },
  { label: t('cms.model.fieldType.fileUpload'), type: 'fileUpload', custom: true },
  { label: t('cms.model.fieldType.editor'), type: 'editor', custom: true }
])
const customs = ref<any[]>([])

watch(visible, async () => {
  if (visible.value && beanId?.value != null) {
    bean.value = await ModelApi.getModelApi(beanId.value)
    customs.value = JSON.parse(bean.value.customs || '[]')
    if (customs.value.length > 0) {
      ;[selected.value] = customs.value
    } else {
      selected.value = undefined
    }
  }
})
const changeSelected = async (element: any) => {
  if (!selected.value) {
    selected.value = element
    return
  }
  selectedForm.value.validate((valid: boolean) => {
    if (valid) {
      selected.value = element
    }
  })
}
const clone = (element: any) => {
  let elementCode = element.custom ? `attr${getRandomLower(6)}` : element.code

  const cloneElement = {
    code: elementCode,
    type: element.type,
    name: element.label,
    custom: element.custom,
    required: element.required,
    double: false
  }
  cloned.value = cloneElement
  return cloneElement
}
const onEnd = (evt: any) => {
  if (evt.from !== evt.to) {
    selected.value = cloned.value
  }
}
const deleteElement = (element: any) => {
  const index = customs.value.indexOf(element)
  customs.value.splice(index, 1)
  const { length } = customs.value
  if (length <= 0) {
    selected.value = undefined
  } else if (index < length) {
    selected.value = customs.value[index]
  } else {
    selected.value = customs.value[length - 1]
  }
}
const handleSubmit = async () => {
  buttonLoading.value = true
  try {
    if (customs.value.length > 0) {
      selectedForm.value.validate(async (valid: boolean) => {
        if (valid) {
          await ModelApi.updateModelApi({
            ...bean.value,
            customs: JSON.stringify(customs.value)
          })
        }
      })
    } else {
      await ModelApi.updateModelApi({
        ...bean.value,
        customs: JSON.stringify(customs.value)
      })
    }
    ElMessage.success(t('common.success'))
  } finally {
    buttonLoading.value = false
    emit('update:modelValue', false)
  }
}
</script>

<style scoped lang="scss">
.drag-component {
  --tw-border-opacity: 0;
  --tw-bg-opacity: 1;

  position: relative;
  display: inline-block;
  width: 100px;
  padding: 0.5rem;
  margin-top: 0.5rem;
  margin-right: 0.5rem;
  font-size: 0.75rem;
  line-height: 1rem;
  cursor: move;
  background-color: rgb(243 244 246 / var(--tw-bg-opacity));
  border-color: rgb(64 158 255 / var(--tw-border-opacity));
  border-style: dashed;
  border-width: 1px;
  border-radius: 0.125rem;
}

.drag-mask {
  --tw-bg-opacity: 1;

  position: absolute;
  top: 0;
  left: 0;
  z-index: 10;
  width: 100%;
  height: 100%;
  cursor: move;
  background-color: rgb(160 207 255 / var(--tw-bg-opacity));
  opacity: 0;
}

.drag-mask-selected {
  --tw-border-opacity: 1;
  --tw-bg-opacity: 1;

  background-color: rgb(160 207 255 / var(--tw-bg-opacity));
  border-color: rgb(64 158 255 / var(--tw-border-opacity));
  border-style: dashed;
  border-width: 1px;
  border-radius: 0.125rem;
  opacity: 0.3;
}

.drag-close {
  position: absolute;
  top: -0.125rem;
  right: 0.125rem;
  z-index: 10;
  cursor: pointer;
  opacity: 0.7;
}

.dialog-full {
  :deep(.el-dialog__body) {
    padding-bottom: 0;
  }
}

.right-panel {
  :deep(.el-form-item) {
    margin-bottom: 14px;
  }
}

.drawing-board {
  .sortable-ghost {
    &::before {
      @apply absolute w-full top-0 left-0 h-1 bg-warning;

      content: ' ';
    }

    .drag-mask {
      opacity: 0.1 !important;
    }

    &.drag-component {
      @apply w-full ml-0 mr-0;
    }
  }

  :deep(.el-scrollbar__view) {
    @apply h-full;
  }
}
.min-h-full{
  min-height: 600px;
}
</style>
